/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.javahispano.javacup.tacticas.tacticas_aceptadas.pringaos2011;

import java.awt.Color;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import org.javahispano.javacup.modelo.AbstractTrayectoria;
import org.javahispano.javacup.modelo.Comando;
import org.javahispano.javacup.modelo.ComandoGolpearBalon;
import org.javahispano.javacup.modelo.ComandoIrA;
import org.javahispano.javacup.modelo.Constantes;
import org.javahispano.javacup.modelo.EstiloUniforme;
import org.javahispano.javacup.modelo.JugadorDetalle;
import org.javahispano.javacup.modelo.Posicion;
import org.javahispano.javacup.modelo.SituacionPartido;
import org.javahispano.javacup.modelo.Tactica;
import org.javahispano.javacup.modelo.TacticaDetalle;
import org.javahispano.javacup.modelo.TrayectoriaAire;

/**
 *
 * @author adou
 */
public class Pringaos2011 implements Tactica {
    Posicion alineacion5[]=new Posicion[]
    {
        new Posicion(0.2595419847328244,-50.41044776119403),
        new Posicion(-11.16030534351145,-35.78358208955224),
        new Posicion(12.717557251908397,-35.26119402985075),
        new Posicion(28.290076335877863,-28.470149253731343),
        new Posicion(-28.290076335877863,-28.470149253731343),
        new Posicion(14.793893129770993,-18.544776119402986),
        new Posicion(-17.389312977099234,-19.58955223880597),
        new Posicion(0.0,-15.0),
        new Posicion(5.969465648854961,-5.485074626865671),
        new Posicion(0.2595419847328244,-0.26119402985074625),
        new Posicion(15.0,-1.0)
    };

    Posicion alineacion6[]=new Posicion[]
    {
        new Posicion(0.2595419847328244,-50.41044776119403),
        new Posicion(-11.16030534351145,-35.78358208955224),
        new Posicion(12.717557251908397,-35.26119402985075),
        new Posicion(28.290076335877863,-28.470149253731343),
        new Posicion(-28.290076335877863,-28.470149253731343),
        new Posicion(14.793893129770993,-18.544776119402986),
        new Posicion(-17.389312977099234,-19.58955223880597),
        new Posicion(0.0,-15.0),
        new Posicion(6.4885496183206115,-6.529850746268657),
        new Posicion(-6.4885496183206115,-6.529850746268657),
        new Posicion(15.0,-1.0)
    };
    class TacticaDetalleImpl implements TacticaDetalle {

        public String getNombre() {
            return "Los Pringaos";
        }

        public String getPais() {
            return "España";
        }

        public String getEntrenador() {
            return "Sito";
        }

        public Color getColorCamiseta() {
            return new Color(255, 0, 0);
        }

        public Color getColorPantalon() {
            return new Color(47, 66, 203);
        }

        public Color getColorFranja() {
            return new Color(255, 255, 255);
        }

        public Color getColorCalcetas() {
            return new Color(255, 0, 0);
        }

        public Color getColorPortero() {
            return new Color(255, 255, 0        );
        }

        public EstiloUniforme getEstilo() {
            return EstiloUniforme.LINEAS_VERTICALES;
        }

        public Color getColorCamiseta2() {
            return new Color(0, 0, 0);
        }

        public Color getColorPantalon2() {
            return new Color(0, 0, 0);
        }

        public Color getColorFranja2() {
            return new Color(255, 0, 0);
        }

        public Color getColorCalcetas2() {
            return new Color(0, 0, 0);
        }

        public Color getColorPortero2() {
            return new Color(255, 255, 0        );
        }

        public EstiloUniforme getEstilo2() {
            return EstiloUniforme.SIN_ESTILO;
        }

        class JugadorImpl implements JugadorDetalle
        {
            String nombre;
            int numero;
            Color piel, pelo;
            double velocidad, remate, precision;
            boolean portero;
            Posicion posicion;

            public JugadorImpl(String nombre, int numero, Color piel, Color pelo,
                    double velocidad, double remate, double precision, boolean portero) {
                this.nombre=nombre;
                this.numero=numero;
                this.piel=piel;
                this.pelo=pelo;
                this.velocidad=velocidad;
                this.remate=remate;
                this.precision=precision;
                this.portero=portero;
            }

            public String getNombre() {
                return nombre;
            }

            public Color getColorPiel() {
                return piel;
            }

            public Color getColorPelo() {
                return pelo;
            }

            public int getNumero() {
                return numero;
            }

            public boolean esPortero() {
                return portero;
            }

            public double getVelocidad() {
                return velocidad;
            }

            public double getRemate() {
                return remate;
            }

            public double getPresicion() {
                return precision;
            }

        }

        public JugadorDetalle[] getJugadores() {
            return new JugadorDetalle[]{
               new JugadorImpl("Calamardo", 1, new Color(255,200,150), new Color(255,200,150),1.0d,1.0d,0.67d, true),
                new JugadorImpl("Bob", 2, new Color(255,102,102), new Color(255,200,150),1.0d,1.0d,0.5d, false),
                new JugadorImpl("Patricio", 3, new Color(255,200,150), new Color(255,200,150),1.0d,1.0d,0.5d, false),
                new JugadorImpl("Billy", 4, new Color(255,200,150), new Color(255,200,150),1.0d,1.0d,0.56d, false),
                new JugadorImpl("Scooby", 5, new Color(255,200,150), new Color(255,200,150),0.71d,0.7d,0.49d, false),
                new JugadorImpl("Calimero", 6, new Color(255,200,150), new Color(255,200,150),0.67d,1.0d,0.69d, false),
                new JugadorImpl("Burt", 7, new Color(255,200,150), new Color(255,200,150),0.67d,1.0d,0.69d, false),
                new JugadorImpl("Hommer", 8, new Color(255,200,150), new Color(255,200,150),0.75d,1.0d,0.64d, false),
                new JugadorImpl("Lisa", 9, new Color(255,200,150), new Color(255,200,150),0.87d,1.0d,0.79d, false),
                new JugadorImpl("Mandy", 10, new Color(255,200,150), new Color(255,200,150),0.85d,1.0d,0.75d, false),
                new JugadorImpl("Berni", 11, new Color(255,200,150), new Color(255,200,150),1.0d,1.0d,1.0d, false)
            };
        }
    }

    class PuntoPase {
        double distancia; // distancia desde el punto de origen
        double puntuacion;
        Posicion p;
    }

    TacticaDetalle detalle=new TacticaDetalleImpl();
    public TacticaDetalle getDetalle() {
        return detalle;
    }


    public static final int ESTADO_EQUIPO_DEFENSA = 1;
    public static final int ESTADO_EQUIPO_ATAQUE = 2;

    public static final int TIPO_JUGADOR_PORTERO = 0;
    public static final int TIPO_JUGADOR_DEFENSA = 1;
    public static final int TIPO_JUGADOR_ATAQUE = 2;

    public final static double MITAD_ANCHO = Constantes.ANCHO_CAMPO_JUEGO / 2;
    public final static double MITAD_LARGO = Constantes.LARGO_CAMPO_JUEGO / 2;

    public int estado_equipo = ESTADO_EQUIPO_DEFENSA;
    public int estado_equipo_anterior = estado_equipo;

    public int tipo_jugadores[] = {TIPO_JUGADOR_PORTERO,
                                   TIPO_JUGADOR_DEFENSA,
                                   TIPO_JUGADOR_DEFENSA,
                                   TIPO_JUGADOR_DEFENSA,
                                   TIPO_JUGADOR_DEFENSA,
                                   TIPO_JUGADOR_DEFENSA,
                                   TIPO_JUGADOR_ATAQUE,
                                   TIPO_JUGADOR_ATAQUE,
                                   TIPO_JUGADOR_ATAQUE,
                                   TIPO_JUGADOR_ATAQUE,
                                   TIPO_JUGADOR_ATAQUE};
    public Posicion[] misJugadores;
    public Posicion[] rivales;
    public JugadorDetalle[] detalleMisJugadores;
    public JugadorDetalle[] detalleRivales;
    public LinkedList<Comando> comandos = new LinkedList<Comando>();
    public boolean []rivales_defendidos = new boolean[11];
    public double [][]posicionesPase;
    public double distanciaOptimaPase = 20.0;


    public double getFuerza(Posicion desde, Posicion hasta, int jugador, double anguloI, double limiteAltura) {
        int i;
        double fuerzaRemate = 1.05;
        double vel;
        AbstractTrayectoria trayectoria;
        double time = 0;
        double desplazamientoHorizontal = 0;
        double desplazamientoVertical = limiteAltura + 1.0;
        double desplazamientoTotal = desde.distancia(hasta);
        double x = desde.getX(), x0 = 0;
        double y = desde.getY(), y0 = 0;
        double aux;
        double distancia;
        double distanciaRival;
        double probabilidad = 0;
        double angulo = anguloI * Math.PI / 180d;
        
        while((fuerzaRemate > 0) && (probabilidad < 0.9)) {
            fuerzaRemate -= 0.05;
            i = 1;
            vel = fuerzaRemate * Constantes.getVelocidadRemate(detalleMisJugadores[jugador].getRemate());
            trayectoria = new TrayectoriaAire(Math.cos(angulo) * vel, Math.sin(angulo) * vel, 0, 0);
            desplazamientoHorizontal = 0;
            distancia = 0;
            aux = 9999;
            while((distancia != aux) && (distancia < desplazamientoTotal)) {
                time = (double) i / 60d;
                aux = distancia;
                desplazamientoHorizontal = trayectoria.getX(time) * Constantes.AMPLIFICA_VEL_TRAYECTORIA;
                desplazamientoVertical = trayectoria.getY(time) * Constantes.AMPLIFICA_VEL_TRAYECTORIA * 2;
                x0 = x;
                y0 = y;
                x = desde.getX() + desplazamientoHorizontal * Math.cos(desde.angulo(hasta) * Math.PI / 180d);
                y = desde.getY() + desplazamientoHorizontal * Math.sin(desde.angulo(hasta) * Math.PI / 180d);
                distancia = desde.distancia(new Posicion(x, y));
                vel = Math.sqrt((x - x0) * (x - x0) + (y - y0) * (y - y0));
                probabilidad = (7d - vel) / 7d;
                // si la probabilidad de interceptar el balon es mayor que el 60% y la altura del balón es menor que el límite -> miro si llega algún rival a este punto
                if ((probabilidad >= 0.5) && (desplazamientoVertical <= limiteAltura)) {
                    for(int f = 0; f < 11; f++) {
                        distanciaRival = rivales[f].distancia(new Posicion(x, y));
                        if ((int) (distanciaRival / detalleRivales[f].getVelocidad()) <= i) {
                            return -1;
                        }
                    }
                }
                i++;
            }
            // si aux es igual a desplazamientoHorizontal es que no llega el pase
            if (distancia == aux) {
                return -1;
            }
        }

        if (desplazamientoVertical > limiteAltura) {
            return -1;
        }

        return fuerzaRemate;
    }

    public boolean dentroCampo(Posicion p)
    {
        return (p.getX() >= -MITAD_ANCHO && p.getX() <= MITAD_ANCHO &&
                p.getY() >= -MITAD_LARGO && p.getY() <= MITAD_LARGO);
    }

    public double[][] calculaPosicionesPase(int pasador) {
        double [][]posiciones;
        int x, y, i, f;
        Posicion origen;

        posiciones = new double[16 * 10][7]; // distancia al punto origen, valor del pase, coordenada x, coordenada y, angulo, fuerza, jugador destino
        i = 0;
        for(f = 1; f < 11; f++) {
            if (f != pasador) {
                origen = misJugadores[f];
                for(x = (int) (origen.getX() - 10); x < (int) origen.getX() + 10; x+=5) {
                    for(y = (int) (origen.getY() - 10); y < (int) origen.getY() + 10; y+=5) {
                        posiciones[i][2] = x;
                        posiciones[i][3] = y;
                        posiciones[i][4] = 0;
                        posiciones[i][5] = 0;
                        posiciones[i][6] = f;
                        if (!dentroCampo(new Posicion(x, y)) || ((x == origen.getX()) && (y == origen.getY()))) {
                            posiciones[i][0] = -1;
                            posiciones[i][1] = -1;
                        } else {
                            posiciones[i][0] = 0; //origen.distancia(new Posicion(x, y));
                            posiciones[i][1] = 0;
                        }
                        //System.out.println("------- Indice Pase: " + i + " + Punto Pase: (" + x + ", " + y + ")" + " + Jugador Destino: " + (int)(posiciones[i][6] + 1));
                        i++;
                    }
                }
            }
        }

        return posiciones;
    }

    public int calculaValorPase(int jugador, Posicion origen) {
        int i;
        double valorMejorPase = 0;
        int indiceMejorPase = 0;
        double fuerza;
        double angulo;
        double distanciaPorteria;
        Posicion posicion;
        
        for(i = 0; i < 16 * 10; i++) {
            if (posicionesPase[i][1] == -1) continue;

            posicion = new Posicion(posicionesPase[i][2], posicionesPase[i][3]);
            angulo = 0;
            fuerza = this.getFuerza(origen, posicion, jugador, angulo, Constantes.ALTURA_CONTROL_BALON);
/*            while((fuerza == -1) && (angulo < Constantes.ANGULO_VERTICAL_MAX)) {
                angulo += 5;
                fuerza = this.getFuerza(origen, posicion, jugador, angulo, Constantes.ALTURA_CONTROL_BALON);
            }*/

            if (fuerza == -1) {
                posicionesPase[i][1] = -1;
                continue;
            } else {
                posicionesPase[i][4] = angulo;
                posicionesPase[i][5] = fuerza;
            }

//            if (posicionesPase[i][0] < distanciaOptimaPase) posicionesPase[i][1] += 0.5; // Es un pase cerca

//            if (posicionesPase[i][3] > 0) posicionesPase[i][1] += 0.25; // es un pase a campo contrario

            distanciaPorteria = posicion.distancia(Constantes.centroArcoSup);
            posicionesPase[i][1] += 1 / distanciaPorteria;
            
            if (valorMejorPase < posicionesPase[i][1]) {
                indiceMejorPase = i;
                valorMejorPase = posicionesPase[i][1];
            }
        }

        return indiceMejorPase;
    }

    private boolean pendienteNoInfinita(Posicion a, Posicion b)
    {
        double denominador = a.getX()-b.getX();
        return (denominador != 0);
    }

    private double calculoPendiente (Posicion a, Posicion b)
    {
        double m = a.getY()-b.getY();
        if (m!=0)
        {
            double denominador = a.getX()-b.getX();
            if (denominador!=0)
            {
                m = m / denominador;
            }
        }
        if (m==Double.NaN)
            return 0;
        else
            return m;
    }

    private double calculoInterseccionEjeY(Posicion a, Posicion b,double pendiente)
    {
        return (a.getY() - pendiente * a.getX());
    }

    public void moverPortero(Posicion pBalonAnterior, Posicion balon)
    {
        // Movimientos portero
        double mPortero,nPortero;
        double xPortero=Constantes.centroArcoInf.getX();
        double yPortero=Constantes.centroArcoInf.getY();
        double mBalon, nBalon;

        // Se calcula la recta que sigue el balon
        double xAux;
        if (this.pendienteNoInfinita(pBalonAnterior, balon))
        {
            mBalon = this.calculoPendiente(pBalonAnterior, balon);
            nBalon = this.calculoInterseccionEjeY(pBalonAnterior, balon, mBalon);

            xAux = (Constantes.posteIzqArcoInf.getY()-nBalon)/mBalon;
        }
        else
        {
            mBalon = Double.POSITIVE_INFINITY;
            nBalon = pBalonAnterior.getX();
            xAux = balon.getX();
        }

        if ((xAux >= Constantes.posteIzqArcoInf.getX()) && (xAux <= Constantes.posteDerArcoInf.getX())) {
                yPortero = Constantes.centroArcoInf.getY()+Constantes.DISTANCIA_CONTROL_BALON_PORTERO;
                xPortero = (yPortero - nBalon) /mBalon;
        } else if (this.pendienteNoInfinita(new Posicion(Constantes.centroArcoInf.getX(),Constantes.centroArcoInf.getY()-1), balon))
        {
            mPortero = this.calculoPendiente(balon,new Posicion(Constantes.centroArcoInf.getX(),Constantes.centroArcoInf.getY()-1));
            nPortero = this.calculoInterseccionEjeY(balon,new Posicion(Constantes.centroArcoInf.getX(),Constantes.centroArcoInf.getY()-1),mPortero);

            yPortero = Constantes.centroArcoInf.getY()+Constantes.DISTANCIA_CONTROL_BALON_PORTERO;
            xPortero =  (yPortero - nPortero) / mPortero;

            if (xPortero<Constantes.posteIzqArcoInf.getX()-1.5) xPortero=Constantes.posteIzqArcoInf.getX()-1.5;
            if (xPortero>Constantes.posteDerArcoInf.getX()+1.5) xPortero=Constantes.posteDerArcoInf.getX()+1.5;
        } else {
            yPortero = Constantes.centroArcoInf.getY()+Constantes.DISTANCIA_CONTROL_BALON_PORTERO;
            xPortero = balon.getX();
            if (xPortero<Constantes.posteIzqArcoInf.getX()-1.5) xPortero=Constantes.posteIzqArcoInf.getX()-1.5;
            if (xPortero>Constantes.posteDerArcoInf.getX()+1.5) xPortero=Constantes.posteDerArcoInf.getX()+1.5;
        }

        comandos.add(new ComandoIrA(0, new Posicion(xPortero, yPortero)));
    }

    public boolean autoPase(int p, Posicion balon) {
        double [][]posiciones = new double[8][3];
        int i, f;
        double distancia;
        double distanciaMinima;
        double aux, aux1;
        int indice;

        if (detalleMisJugadores[p].esPortero()) return false;

        distancia = detalleMisJugadores[p].getVelocidad() * Constantes.ITERACIONES_GOLPEAR_BALON;
        posiciones[0][0] = misJugadores[p].getX() + distancia;
        posiciones[0][1] = misJugadores[p].getY();
        posiciones[1][0] = misJugadores[p].getX();
        posiciones[1][1] = misJugadores[p].getY() + distancia;
        posiciones[2][0] = misJugadores[p].getX() - distancia;
        posiciones[2][1] = misJugadores[p].getY();
        posiciones[3][0] = misJugadores[p].getX();
        posiciones[3][1] = misJugadores[p].getY() - distancia;
        posiciones[4][0] = misJugadores[p].getX() + (distancia / 2);
        posiciones[4][1] = misJugadores[p].getY() + (distancia / 2);
        posiciones[5][0] = misJugadores[p].getX() - (distancia / 2);
        posiciones[5][1] = misJugadores[p].getY() + (distancia / 2);
        posiciones[6][0] = misJugadores[p].getX() + (distancia / 2);
        posiciones[6][1] = misJugadores[p].getY() - (distancia / 2);
        posiciones[7][0] = misJugadores[p].getX() - (distancia / 2);
        posiciones[7][1] = misJugadores[p].getY() - (distancia / 2);

        aux1 = 0;
        indice = 0;
        for(i = 0; i < 7; i++) {
            distanciaMinima = 999;
            for(f = 0; f < 11; f++) {
                aux = rivales[f].distancia(new Posicion(posiciones[i][0], posiciones[i][1]));
                if (aux < distanciaMinima) {
                    posiciones[i][2] = aux;
                    aux = distanciaMinima;
                }
            }
            if (aux1 > posiciones[i][2]) {
                aux1 = posiciones[i][2];
                indice = i;
            }
        }

        if (posiciones[indice][2] < distancia) return false;

        double fuerza = this.getFuerza(balon, new Posicion(posiciones[indice][0], posiciones[indice][1]), p, 0, Constantes.ALTURA_CONTROL_BALON);
        comandos.add(new ComandoGolpearBalon(p, new Posicion(posiciones[indice][0], posiciones[indice][1]), fuerza, 0));
        comandos.add(new ComandoIrA(p, new Posicion(posiciones[indice][0], posiciones[indice][1])));

        return true;
    }

    public boolean tiroAPuerta(int p, Posicion pos) {
        double inc;
        int i;
        double fuerza = 0;

        inc = Constantes.LARGO_ARCO / 5;
        for(i = 0; i < 5; i++) {
            fuerza = this.getFuerza(pos, new Posicion(Constantes.posteIzqArcoSup.getX() + (inc * i), Constantes.posteIzqArcoSup.getY()), p, 0, Constantes.ALTO_ARCO);
            if (fuerza != -1) {
                comandos.add(new ComandoGolpearBalon(p, new Posicion(Constantes.posteIzqArcoSup.getX() + (inc * i), Constantes.posteIzqArcoSup.getY()), fuerza, 0));
                return true;
            }
        }

        return false;
    }

    public void mueveDelanteros(Posicion balon) {
        if (balon.getY()<0) {
            if (balon.getX()>15)
            {
                comandos.add(new ComandoIrA(5, new Posicion(balon.getX()-45,balon.getY()+10)));
                comandos.add(new ComandoIrA(6, new Posicion(balon.getX(),balon.getY()+10)));
                comandos.add(new ComandoIrA(7, new Posicion(10.0,balon.getY()+20)));
                comandos.add(new ComandoIrA(8, new Posicion(balon.getX(),balon.getY()+20)));
                comandos.add(new ComandoIrA(9, new Posicion(balon.getX()-20,balon.getY()+30)));
            }
            else if (balon.getX()<-15)
            {
                comandos.add(new ComandoIrA(5, new Posicion(balon.getX(),balon.getY()+10)));
                comandos.add(new ComandoIrA(6, new Posicion(balon.getX()+45,balon.getY()+10)));
                comandos.add(new ComandoIrA(7, new Posicion(-10.0,balon.getY()+20)));
                comandos.add(new ComandoIrA(8, new Posicion(balon.getX()+20,balon.getY()+20)));
                comandos.add(new ComandoIrA(9, new Posicion(balon.getX(),balon.getY()+30)));
            }
            else
            {
                comandos.add(new ComandoIrA(5, new Posicion(balon.getX()-20,balon.getY()+10)));
                comandos.add(new ComandoIrA(6, new Posicion(balon.getX()+20,balon.getY()+10)));
                comandos.add(new ComandoIrA(7, new Posicion(balon.getX(),balon.getY()+20)));
                comandos.add(new ComandoIrA(8, new Posicion(balon.getX()+20,balon.getY()+30)));
                comandos.add(new ComandoIrA(9, new Posicion(balon.getX()-20,balon.getY()+30)));
            }
            comandos.add(new ComandoIrA(10, new Posicion(balon.getX(),balon.getY()+50)));
        }
        else
        {
            double yAux=balon.getY()+30;
            if (yAux>Constantes.LARGO_CAMPO_JUEGO/2.0)
                yAux=(Constantes.LARGO_CAMPO_JUEGO/2.0)-10;
            if (balon.getX()>15)
            {
                comandos.add(new ComandoIrA(5, new Posicion(balon.getX()-55,balon.getY()-5)));
                comandos.add(new ComandoIrA(6, new Posicion(balon.getX(),balon.getY()-5)));
                comandos.add(new ComandoIrA(7, new Posicion(10.0,balon.getY()-15)));
                comandos.add(new ComandoIrA(8,new Posicion(balon.getX()-5,yAux)));
                comandos.add(new ComandoIrA(9,new Posicion(Constantes.posteIzqArcoSup.getX()+1,balon.getY())));
            }
            else if (balon.getX()<-15)
            {
                comandos.add(new ComandoIrA(5, new Posicion(balon.getX(),balon.getY()-5)));
                comandos.add(new ComandoIrA(6, new Posicion(balon.getX()+55,balon.getY()-5)));
                comandos.add(new ComandoIrA(7, new Posicion(-10.0,balon.getY()-15)));
                comandos.add(new ComandoIrA(8,new Posicion(Constantes.posteDerArcoSup.getX()-1,balon.getY())));
                comandos.add(new ComandoIrA(9,new Posicion(balon.getX()+5,yAux)));
            }
            else
            {
                comandos.add(new ComandoIrA(5, new Posicion(balon.getX()-20,balon.getY()-5)));
                comandos.add(new ComandoIrA(6, new Posicion(balon.getX()+20,balon.getY()-5)));
                comandos.add(new ComandoIrA(7, new Posicion(balon.getX(),balon.getY()-15)));
                comandos.add(new ComandoIrA(8,new Posicion(balon.getX()+10,yAux)));
                comandos.add(new ComandoIrA(9,new Posicion(balon.getX()-10,yAux)));
            }
            int portero=0;
            for (int i=0;i<11;i++)
            {
                if (detalleRivales[i].esPortero())
                {
                    portero=i;
                }
            }
            comandos.add(new ComandoIrA(10, new Posicion(rivales[portero].getX(),rivales[portero].getY()-4.9)));
        }

    }

    public List<Comando> ejecutar(SituacionPartido sp) {
        int i, j, aux;
        double distancia, distancia_aux, x, y;
        int indicePase;

        // control de jugadores
        misJugadores = sp.misJugadores();
        rivales = sp.rivales();
        detalleMisJugadores = sp.detalleMisJugadores();
        detalleRivales = sp.detalleJugadoresRivales();


        comandos.clear();

        // Establecemos estado del equipo
        if ((sp.sacaRival()) || ((sp.puedenRematarRival().length > 0) && (sp.puedenRematar().length == 0)))
        {
            estado_equipo_anterior = estado_equipo;
            estado_equipo = ESTADO_EQUIPO_DEFENSA;
        }
        else {
                estado_equipo_anterior = estado_equipo;
                estado_equipo = ESTADO_EQUIPO_ATAQUE;
            }

        // PORTERO
        this.moverPortero(sp.balon(), new Posicion(sp.getTrayectoria(1)[0], sp.getTrayectoria(1)[1]));

        // DEFENSAS
        for(i = 0; i < 11; i++) {
            rivales_defendidos[i] = false;
        }

        for(i = 0; i < 11; i++) {
            if (tipo_jugadores[i] == TIPO_JUGADOR_DEFENSA) {
                distancia = 999;
                aux = 10;
                for(j = 10; j >= 0; j--) {
                    distancia_aux = Math.sqrt(Math.pow(sp.rivales()[j].getX() - Constantes.centroArcoInf.getX(),2) + Math.pow(sp.rivales()[j].getY()-Constantes.centroArcoInf.getY(),2));
                    if ((distancia_aux < distancia) && (!rivales_defendidos[j]))
                    {
                        distancia = distancia_aux;
                        aux = j;
                    }
                }
                rivales_defendidos[aux] = true;

                x = sp.rivales()[aux].getX();
                if (sp.balon().getY() > sp.rivales()[aux].getY())
                {
                    y = sp.rivales()[aux].getY() + 2;
                }
                else
                {
                    y = sp.rivales()[aux].getY() - 2;
                }
                comandos.add(new ComandoIrA(i, new Posicion(x,y)));
            } else if (tipo_jugadores[i] == TIPO_JUGADOR_ATAQUE) {
                mueveDelanteros(sp.balon());
            }
        }

        if (!sp.sacaRival()) {
            //Obtiene los datos de recuperacion del balon
            int[] recuperadores = sp.getRecuperacionBalon();
            //Si existe posibilidad de recuperar el balon
            if (recuperadores.length > 1) {
                //Obtiene las coordenadas del balon en el instante donde
                //se puede recuperar el balon
                double[] posRecuperacion = sp.getTrayectoria(recuperadores[0]);
                for (i = 1; i < recuperadores.length; i++) {
                    //Ordena a los jugadores recuperadores que se ubique
                    //en la posicion de recuperacion
                    comandos.add(new ComandoIrA(recuperadores[i],
                            new Posicion(posRecuperacion[0], posRecuperacion[1])));
                }
            }
        }

        //Instancia un generador aleatorio
        Random r = new Random();
        //Recorre la lista de mis jugadores que pueden rematar
        for (int  p : sp.puedenRematar()) {
            if (!tiroAPuerta(p, sp.balon())) {
                posicionesPase = calculaPosicionesPase(p);
                indicePase = calculaValorPase(p, sp.balon());

                if (posicionesPase[indicePase][1] == -1) {
                    if (!autoPase(p, sp.balon())) {
                        // despejo el balón
                        comandos.add(new ComandoGolpearBalon(p, Constantes.centroArcoSup, 1, 12 + r.nextInt(6)));

                   //     System.out.println("******** Despejo Balon!!!!!");
                    }
                } else {
                    comandos.add(new ComandoGolpearBalon(p, new Posicion(posicionesPase[indicePase][2], posicionesPase[indicePase][3]),
                                                         posicionesPase[indicePase][5], posicionesPase[indicePase][4]));
                    comandos.add(new ComandoIrA((int) posicionesPase[indicePase][6], new Posicion(posicionesPase[indicePase][2], posicionesPase[indicePase][3])));

                 //   System.out.println("------- Indice Pase: " + indicePase + " + Origen: " + (p + 1) + " + Destino: " + ((int)(posicionesPase[indicePase][6]) + 1) + " + Fuerza: " + posicionesPase[indicePase][5] + " + Angulo: " + posicionesPase[indicePase][4]);
                }
            }
        }

        return comandos;
    }

    @Override
    public Posicion[] getPosicionSaca(SituacionPartido sp) {
        return alineacion5;
    }

    @Override
    public Posicion[] getPosicionRecive(SituacionPartido sp) {
        return alineacion6;
    }

}
